package com.gillion.grule.client.sync;

import com.alibaba.fastjson.JSON;
import com.gillion.grule.client.core.BusinessModelAttribute;
import com.gillion.grule.client.core.DroolsRuleCompiler;
import com.gillion.grule.client.core.variable.AssemblyVariable;
import com.gillion.grule.client.core.variable.PackageVariable;
import com.gillion.grule.client.core.variable.RuleVariable;
import com.google.common.collect.Maps;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.drools.compiler.builder.impl.KnowledgeBuilderImpl;
import org.drools.core.RuleBaseConfiguration;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceType;
import org.kie.internal.KnowledgeBase;
import org.kie.internal.builder.KnowledgeBuilderConfiguration;
import org.kie.internal.builder.KnowledgeBuilderFactory;



public class DroolsRulePackage extends RulePackage implements Serializable {

    private KnowledgeBase knowledgeBase;

    public String toString() { return "DroolsRulePackage(knowledgeBase=" + getKnowledgeBase() + ", assemblys=" + getAssemblys() + ", content=" + getContent() + ")"; }


    private Map<String, DroolsRuleAssembly> assemblys = Maps.newConcurrentMap();



    private String content;




    public void compile(DroolsRuleCompiler compiler) {
        KnowledgeBuilderConfiguration kbConfig = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration();
        kbConfig.setProperty("drools.dialect.mvel.strict", "false");
        kbConfig.setProperty("drools.dialect.java.strict", "false");


        KnowledgeBuilderImpl knowledgeBuilder = (KnowledgeBuilderImpl)KnowledgeBuilderFactory.newKnowledgeBuilder(kbConfig);
        Resource resource = compiler.compile(this.content);
        knowledgeBuilder.add(resource, ResourceType.DRL);
        RuleBaseConfiguration ruleBaseConfiguration = new RuleBaseConfiguration();
        ruleBaseConfiguration.setJittingThreshold(2147483647);
        this.knowledgeBase = knowledgeBuilder.newKnowledgeBase((KieBaseConfiguration)ruleBaseConfiguration);
        readyVariable();

        if (this.assemblys != null && !this.assemblys.isEmpty()) {
            Set<String> keySet = this.assemblys.keySet();
            for (String key : keySet) {
                ((DroolsRuleAssembly)this.assemblys.get(key)).setName(key);
                ((DroolsRuleAssembly)this.assemblys.get(key)).compile(compiler);
            }
        }
    }




    private void readyVariable() {
        Map<String, AssemblyVariable> assemblyVariables = this.variables.getAssemblyVariables();
        if (assemblyVariables != null && !assemblyVariables.isEmpty()) {
            Set<String> keys = assemblyVariables.keySet();
            for (String key : keys) {
                ((AssemblyVariable)assemblyVariables.get(key))
                        .setPackageVariable(this.variables);
                Map<String, RuleVariable> ruleVariables = ((AssemblyVariable)assemblyVariables.get(key)).getRuleVariables();
                if (ruleVariables == null || ruleVariables.isEmpty()) {
                    continue;
                }

                Set<String> ruleNames = ruleVariables.keySet();
                for (String ruleName : ruleNames) {
                    ((RuleVariable)ruleVariables.get(ruleName)).setAssemblyVariable(assemblyVariables.get(key));
                }
            }
        }
    }








    public void addAssembly(String asseblyName, DroolsRuleAssembly droolsRuleAssembly) {
        if (this.assemblys == null) {
            this.assemblys = Maps.newConcurrentMap();
        }
        this.assemblys.put(asseblyName, droolsRuleAssembly);
    }

    public KnowledgeBase getKnowledgeBase() {
        return this.knowledgeBase;
    }

    public void setKnowledgeBase(KnowledgeBase knowledgeBase) {
        this.knowledgeBase = knowledgeBase;
    }

    public Map<String, DroolsRuleAssembly> getAssemblys() {
        return this.assemblys;
    }

    public void setAssemblys(Map<String, DroolsRuleAssembly> assemblys) {
        this.assemblys = assemblys;
    }

    public String getContent() {
        return this.content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public DroolsRulePackage clone() {
        DroolsRulePackage drp = new DroolsRulePackage();
        drp.setGroupId(getGroupId());
        drp.setKnowledgeBase(getKnowledgeBase());
        drp.setContent(getContent());
        drp.setArtifactId(getArtifactId());
        drp.setVersion(getVersion());
        drp.setDubboConfigs(getDubboConfigs());
        drp.setRemoteConfig(getRemoteConfig());
        drp.setGroovyShellConfigs(getGroovyShellConfigs());
        drp.setSpringCloudConfig(getSpringCloudConfig());
        drp.setDataSources(getDataSources());
        List<BusinessModelAttribute> modelList = new ArrayList<>();
        for (BusinessModelAttribute bma : getBusinessModelAttributes()) {
            BusinessModelAttribute b = new BusinessModelAttribute();
            b.setName(bma.getName());
            b.setIsMust(bma.getIsMust());
            b.setValueExpress(bma.getValueExpress());
            b.setDataType(bma.getDataType());
            b.setValueType(bma.getValueType());
            modelList.add(b);
        }
        drp.setBusinessModelAttributes(modelList);
        drp.setStatus(getStatus());

        Map<String, DroolsRuleAssembly> assemblys = new HashMap<>();
        for (String assName : getAssemblys().keySet()) {
            DroolsRuleAssembly dra = new DroolsRuleAssembly();
            dra.setName(((DroolsRuleAssembly)getAssemblys().get(assName)).getName());
            dra.setContent(((DroolsRuleAssembly)getAssemblys().get(assName)).getContent());
            dra.setKnowledgeBase(((DroolsRuleAssembly)getAssemblys().get(assName)).getKnowledgeBase());
            dra.setAssemblys(null);
            assemblys.put(assName, dra);
        }
        drp.setAssemblys(assemblys);
        drp.setVariables((PackageVariable)JSON.parseObject(JSON.toJSONString(getVariables()), PackageVariable.class));

        return drp;
    }
}